/*
 * PBBWikiCoder.java
 *
 * Created on May 29, 2007, 3:58 PM
 *
 * A class to build wiki code from certain data.
 *  Example Code for he Protein Box:
 *
 *
 *{{GNF_Protein_box
 | image=1snx.png
 | image_source = {{PDB2|1SNX}}
 | PDB = {{PDB2|1SNX}}, {{PDB2|2ETZ}}, {{PDB2|2EU0}}, {{PDB2|1LUK}}, {{PDB2|1LUM}}, {{PDB2|1LUN}}, {{PDB2|1LUI}}, {{PDB2|1AWJ}}, {{PDB2|1SNU}}, {{PDB2|1SM2}}
 | Name=IL2-inducible T-cell kinase
 | HGNCid = 6171
 | Symbol = ITK
 | AltSymbols =; EMT; LYK; PSCTK2; MGC126257; MGC126258
 | OMIM = 186973
 | ECnumber =
 | Homologene = 4051
 | MGIid = 96621
 | GeneAtlas_image = Itk_GNF1Hthumb.png
 | Function =
{{GNF_GO|id=GO:0000166}} {{GNF_GO|id=GO:0004715}} {{GNF_GO|id=GO:0005524}} {{GNF_GO|id=GO:0006468}} {{GNF_GO|id=GO:0006968}}{{GNF_GO|id=GO:0007242}}{{GNF_GO|id=GO:0008270}}{{GNF_GO|id=GO:0016301}}{{GNF_GO|id=GO:0016740}}{{GNF_GO|id=GO:0046872}}
 | Orthologs = {{GNF_Ortholog_box
    | Hs_EntrezGene = 3702
    | Hs_Ensembl = ENSG00000113263
    | Hs_RefseqmRNA = NM_005546
    | Hs_RefseqProtein = NP_005537
    | Hs_GenLoc_db = hg17
    | Hs_GenLoc_chr =5
    | Hs_GenLoc_start = 156539432
    | Hs_GenLoc_end = 156615687
    | Hs_expression = {{GNF_SymAtlas | ID=211339_s_at}}
    | Hs_Uniprot = Q08881
    | Mm_EntrezGene = 16428
    | Mm_Ensembl = ENSMUSG00000020395
    | Mm_RefseqmRNA = NM_010583
    | Mm_RefseqProtein = NP_034713
    | Mm_GenLoc_db = mm7
    | Mm_GenLoc_chr =11
    | Mm_GenLoc_start = 46280906
    | Mm_GenLoc_end = 46347246
    | Mm_expression = {{GNF_SymAtlas | ID= 103028_at}} <br>{{GNF_SymAtlas | ID= 1417171_at}} <br>{{GNF_SymAtlas | ID= 1452518_a_at}} <br>{{GNF_SymAtlas | ID= 1457120_at}}
    | Mm_Uniprot = Q03526
  }}
}}
 *
 * Copyright 2007-2008 Jon W Huss III

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 *
 */

package proteinboxbot;

import java.util.Hashtable;
import proteinboxbot.*;

/**
 *
 * @author Jon Huss
 */
public class PBBWikiCoder {
    
    private Hashtable<String,String> goTerms;
    private PBBLogging log;
    private PBBdata data;
    
    private String lineSep;
    
    //Used to hold pubmed citations for the gene
    private String[] citationData = null;
    
    /** Creates a new instance of PBBWikiCoder */
    public PBBWikiCoder(PBBdata d, Hashtable<String,String> goTs,PBBLogging l) {
        goTerms = goTs;
        log = l;
        data = d;
        lineSep = lineSep = System.getProperty("line.separator");
        
    }
    
    public String getGoTerm(String id){
        //returns a description of a go term based on the key (id).
        if (goTerms == null){
            return "";
        }
        String val = "";
        if (goTerms.containsKey(id)){
            val = goTerms.get(id);
        }
        return val;
    }
    
    public String getEntrezRef() {
        //returns a reference line usually to be placed at the end of the summary.
        //<ref>
        //{{cite web
        //| title= Entrez Gene: PPARG peroxisome proliferator-activated receptor gamma
        //| url=http://www.ncbi.nlm.nih.gov/sites/entrez?Db=gene&Cmd=ShowDetailView&TermToSearch=5468
        //| accessdate = 2007-08-13}}
        //</ref>
        
        String ref = "<ref name=\"entrez\">{{cite web " +
                "| title = Entrez Gene: " + data.getValue("Symbol" ,true) + " " + data.getValue("Name", true) +
                "| url = http://www.ncbi.nlm.nih.gov/sites/entrez?Db=gene&Cmd=ShowDetailView&TermToSearch=" + data.getValue("Ref_Num",true) +
                "| accessdate = " + //data.getValue("AccessDate",true) +  //Removed due to potential time lag.
                "}}</ref>";
        return ref;
    }
    
    public String getRefFooters() {
        
        return "==References==" + lineSep + "{{reflist}}" + lineSep;
    }
    
    public String getFurtherReadingHeaders() {
        String data = "";
        //Only want the section header to popup if there are citations..
        if (citationData != null){
            if (citationData.length > 0){
                
                data += "==Further reading==" + lineSep;
            }
        }
        data += "{{refbegin | 2}}" + lineSep;
        return data;
    }
    public String getFurtherReadingFooters() {
        
        String lineSep = System.getProperty("line.separator");
        String data = "{{refend}}" + lineSep;
        return data;
    }
    public String getFurtherReadingCitations() {
        
        if (citationData == null){
            //just return a blank box...
            return "{{PBB_Further_reading " + lineSep +
                    "| citations = " + lineSep + "}}";
            
        }
        
        String data = "{{PBB_Further_reading " + lineSep +
                "| citations = " + lineSep;
        //Return the citations in bullet point format.
        for (int i =0; i < citationData.length; i++){
            if (citationData[i].compareTo("") != 0){
                data += "*" + citationData[i] + lineSep;
            }
        }
        data += "}}";
        return data;
    }
    
    public String getWikiCodePB() {
        //returns just the GNF_Protein_Box code
        String[] vals = null;
        
        String wikiCode = "";
        
        //Begin Protein Box
        wikiCode = wikiCode + "{{GNF_Protein_box" + lineSep;
        wikiCode = wikiCode + " | image = " + data.getValue("image",true) + lineSep;
        wikiCode = wikiCode + " | image_source = " + data.getValue("image_source",true) + lineSep;
        //wikiCode = wikiCode + " | PDB = " + data.getValues("PDB", ", ",true) + lineSep;
        //Special Handling of PDB entries required.
        wikiCode = wikiCode + " | PDB = ";
        vals =  data.getValueList("PDB");
        for(int i = 0; i < vals.length; i++){
            if (vals[i].trim().compareTo("") !=0){
                //String desc = this.getGoTerm(vals[i]);
                String front = "{{PDB2|" + vals[i] + "}}";
                String back = "";
                if (i + 1 < vals.length){
                    //Not the end of the entries, so add a comma.
                    back = ", ";
                }
                //if ("".compareTo(desc) == 0){
                //    log.addEntry(data.getValue("Symbol",true),"Warning","No Description found for GO Term: " + vals[i],PBBLogging.logs.ER);
                //    System.out.println("Warning: no description found for GO term: "+ vals[i]);
                //    back = "}} ";
                //}else {
                //    back = " |text = " + desc + "}} ";
                //}
                //System.out.println(vals[i]); //DEBUG XXX
                wikiCode = wikiCode + front + back;
            }
        }
        wikiCode = wikiCode + lineSep; //Finish off the PDB line.
        
        wikiCode = wikiCode + " | Name = " + this.capitalizeFirstLetter(data.getValue("Name",true)) + lineSep;
        wikiCode = wikiCode + " | HGNCid = " + data.getValue("HGNCid",true) + lineSep;
        wikiCode = wikiCode + " | Symbol = " + data.getValue("Symbol",true) + lineSep;
        wikiCode = wikiCode + " | AltSymbols =; " + data.getValues("AltSymbols", "; ",true) + lineSep;
        wikiCode = wikiCode + " | OMIM = " + data.getValue("OMIM",true) + lineSep;
        wikiCode = wikiCode + " | ECnumber = " + data.getValue("ECnumber",true) + lineSep;
        wikiCode = wikiCode + " | Homologene = " + data.getValue("Homologene",true) + lineSep;
        wikiCode = wikiCode + " | MGIid = " + data.getValue("MGIid",true) + lineSep;
        
        //Add up to three GeneAtlas images to the Box...
        vals = data.getValueList("GeneAtlas_image");
        int imageCount = 1;
        for(int i = 0; i < vals.length && imageCount < 4; i++){
            if (vals[i].trim().compareTo("") !=0){
                String desc = this.getGoTerm(vals[i]);
                //wikiCode = wikiCode + " | GeneAtlas_image = ";
                String front = " | GeneAtlas_image"+ imageCount +" = " + vals[i];
                //String back = "]] ";
                wikiCode = wikiCode + front + lineSep;
                imageCount++;
            }
        }
        //wikiCode = wikiCode + lineSep;
        
        
        //This does not actually do anything except place a time stamp of the last bot update.
        //wikiCode = wikiCode + " <!-- The Following entry is a time stamp of the last bot update.  It is typically hidden data -->" + lineSep;
        //wikiCode = wikiCode + " | DateOfBotUpdate = ~~~~~" + lineSep;
        
        //some special handling of Go Term Function/Component/Process values required.
        
        wikiCode = wikiCode + " | Function = ";
        vals =  data.getValueList("Function");
        for(int i = 0; i < vals.length; i++){
            if (vals[i].trim().compareTo("") !=0){
                String desc = this.getGoTerm(vals[i]);
                String front = "{{GNF_GO|id="+vals[i];
                String back = "";
                if ("".compareTo(desc) == 0){
                    log.addEntry(data.getValue("Symbol",true),"Warning","No Description found for GO Term: " + vals[i],PBBLogging.logs.ER);
                    System.out.println("Warning: no description found for GO term: "+ vals[i]);
                    back = "}}";
                }else {
                    back = " |text = " + desc + "}}";
                }
                //System.out.println(vals[i]); //DEBUG XXX
                wikiCode = wikiCode + front + back;
            }
        }
        
        wikiCode = wikiCode + lineSep;
        wikiCode = wikiCode + " | Component = ";
        vals =  data.getValueList("Component");
        for(int i = 0; i < vals.length; i++){
            if (vals[i].trim().compareTo("") !=0){
                String desc = this.getGoTerm(vals[i]);
                String front = "{{GNF_GO|id="+vals[i];
                String back = "";
                if ("".compareTo(desc) == 0){
                    log.addEntry(data.getValue("Symbol",true),"Warning","No Description found for GO Term: " + vals[i],PBBLogging.logs.ER);
                    System.out.println("Warning: no description found for GO term: "+ vals[i]);
                    back = "}} ";
                }else {
                    back = " |text = " + desc + "}} ";
                }
                //System.out.println(vals[i]); //DEBUG XXX
                wikiCode = wikiCode + front + back;
            }
        }
        
        wikiCode = wikiCode + lineSep;
        wikiCode = wikiCode + " | Process = ";
        vals =  data.getValueList("Process");
        for(int i = 0; i < vals.length; i++){
            if (vals[i].trim().compareTo("") !=0){
                String desc = this.getGoTerm(vals[i]);
                String front = "{{GNF_GO|id="+vals[i];
                String back = "";
                if ("".compareTo(desc) == 0){
                    log.addEntry(data.getValue("Symbol",true),"Warning","No Description found for GO Term: " + vals[i],PBBLogging.logs.ER);
                    System.out.println("Warning: no description found for GO term: "+ vals[i]);
                    back = "}} ";
                }else {
                    back = " |text = " + desc + "}} ";
                }
                //System.out.println(vals[i]); //DEBUG XXX
                wikiCode = wikiCode + front + back;
            }
        }
        
        wikiCode = wikiCode + lineSep;
        //begin Ortholog box
        wikiCode = wikiCode + " | Orthologs = {{GNF_Ortholog_box" + lineSep;
        wikiCode = wikiCode + "    | Hs_EntrezGene = " + data.getValue("Hs_EntrezGene",true) + lineSep;
        wikiCode = wikiCode + "    | Hs_Ensembl = " + data.getValue("Hs_Ensembl",true) + lineSep;
        wikiCode = wikiCode + "    | Hs_RefseqProtein = " + data.getValue("Hs_RefseqProtein",true) + lineSep;
        
        //Quick catch for error value "\N":
        wikiCode = wikiCode + "    | Hs_RefseqmRNA = ";
        if (data.getValue("Hs_RefseqmRNA",true).compareTo("\\N") == 0){
            wikiCode = wikiCode + " " + lineSep;
        } else {
            wikiCode = wikiCode + data.getValue("Hs_RefseqmRNA",true) + lineSep;
        }
        wikiCode = wikiCode + "    | Hs_GenLoc_db = " + data.getValue("Hs_GenLoc_db",true) + lineSep;
        wikiCode = wikiCode + "    | Hs_GenLoc_chr = " + data.getValue("Hs_GenLoc_chr",true) + lineSep;
        wikiCode = wikiCode + "    | Hs_GenLoc_start = " + data.getValue("Hs_GenLoc_start",true) + lineSep;
        wikiCode = wikiCode + "    | Hs_GenLoc_end = " + data.getValue("Hs_GenLoc_end",true) + lineSep;
        //wikiCode = wikiCode + "    | Hs_expression = " + data.getValues("Hs_expression", " <br>",true) + lineSep;
        wikiCode = wikiCode + "    | Hs_Uniprot = " + data.getValue("Hs_Uniprot",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_EntrezGene = " + data.getValue("Mm_EntrezGene",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_Ensembl = " + data.getValue("Mm_Ensembl",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_RefseqmRNA = " + data.getValue("Mm_RefseqmRNA",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_RefseqProtein = " + data.getValue("Mm_RefseqProtein",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_GenLoc_db = " + data.getValue("Mm_GenLoc_db",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_GenLoc_chr = " + data.getValue("Mm_GenLoc_chr",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_GenLoc_start = " + data.getValue("Mm_GenLoc_start",true) + lineSep;
        wikiCode = wikiCode + "    | Mm_GenLoc_end = " + data.getValue("Mm_GenLoc_end",true) + lineSep;
        //wikiCode = wikiCode + "    | Mm_expression = {{" + data.getValues("Mm_expression", "}} <br>{{",true) +"}}"+ lineSep;
        wikiCode = wikiCode + "    | Mm_Uniprot = " + data.getValue("Mm_Uniprot",true) + lineSep;
        
        wikiCode = wikiCode + "  }}" + lineSep;
        //End Ortholog Box
        
        wikiCode = wikiCode + "}}";
        //End Protein Box
        return wikiCode;
        
    }
    
    public static String capitalizeFirstLetter(String in) {
        
        if (in == null){
            return null;
        }
        if (in.length() < 1) {
            return in;
        }
        if (in.length() == 1) {
            return in.toUpperCase();
        }
        //Now that the error checking is out of the way...
        
        String first = in.substring(0,1);
        String rest = in.substring(1);
        first = first.toUpperCase();
        return first+rest;
    }
    
    public String getWikiCodeSum(){
        return this.getWikiCodeSum(""); //default
    }
    
    public String getWikiCodeSum(String sectionTitle) {
        //returns only the text summary.
        String wikiCode = "";
        
        if (data.getValue("Text",false).trim().compareTo("") != 0){
            wikiCode = "{{PBB_Summary" + lineSep +
                    "| section_title = " + sectionTitle + lineSep +
                    "| summary_text = ";
            
            
            //Now for the text data.
            //wikiCode = wikiCode + "==Summary==" + lineSep;
            wikiCode = wikiCode + data.getValue("Text",false) + this.getEntrezRef() + lineSep;
            wikiCode += "}}";
        } else {
            //Still need a blank summary box...
            wikiCode  = "{{PBB_Summary" + lineSep +
                    "| section_title = " + lineSep +
                    "| summary_text = " + lineSep +
                    "}}";
            //wikiCode + "<!-- No Summary Available -->" + lineSep;
        }
        
        return wikiCode;
    }
    
    public String getWikiCodeBoxHeaders() {
        
        String header = "";
        //header = "<!-- BOT: PROTEIN BOX UPDATE = YES" +
        //        " - This protein box is automatically updated by protein box bot." +
        //        " Change the update option to NO to have the bot skip updating this protein box -->" +
        //        lineSep;
        header = "<!-- The GNF_Protein_box is automatically maintained by Protein Box Bot.  See Template:PBB_Controls to Stop updates. -->" + lineSep;
        return header;
    }
    public String getWikiCodeSumHeaders() {
        
        String header = "";
        //header = "<!-- BOT: SUMMARY BEGIN UPDATE = YES " +
        //        "- This summary is automatically updated by protein box bot.  " +
        //        "Change the update option to NO to have the bot skip updating this summary -->" +
        //       lineSep;
        header += "'''" +this.capitalizeFirstLetter(data.getValue("Name",true)) + "''', also known as '''" +
                data.getValue("Symbol",true) + "''', is a human [[gene]]." +this.getEntrezRef()+ lineSep + lineSep;
        header += "<!-- The PBB_Summary template is automatically maintained by Protein Box Bot.  See Template:PBB_Controls to Stop updates. -->" + lineSep;
        return header;
    }
    
    public String getWikiCodeSumFooters() {
        
        String header = "";
        //header = "<!-- BOT: SUMMARY END -->" + lineSep;
        
        return header;
    }
    
    public String getWikiBotControlBox() {
        
        String data = "{{PBB_Controls" + lineSep +
                "| update_page = yes " + lineSep +
                "| require_manual_inspection = no " + lineSep +
                "| update_protein_box = yes" + lineSep +
                "| update_summary = yes" + lineSep +
                "| update_citations = yes" + lineSep +
                "}}";
        return data;
    }
    
    public String getWikiCodePageHeaders() {
        
        String header = "<!-- The PBB_Controls template provides controls for Protein Box Bot, please see Template:PBB_Controls for details. -->" + lineSep;
        header += this.getWikiBotControlBox() + lineSep;
        //Moved this code as a summary header.
        //header += "'''" +this.capitalizeFirstLetter(data.getValue("Name",true)) + "''', also known as '''" +
        //        data.getValue("Symbol",true) + "''', is a human [[gene]].";
        return header;
    }
    
    public String getWikiCodeFullSum() {
        //returns the headers and footers too.
        //if (data.getValue("Text",false).trim().compareTo("") != 0){
        return getWikiCodeSumHeaders() + getWikiCodeSum() + lineSep + getWikiCodeSumFooters();
        //}else {
        //    return getWikiCodeSumHeaders() + "<!-- No Summary Available -->"+ getWikiCodeSumFooters();
        // }
        
    }
    public String getWikiCodeFullPB() {
        
        return this.getWikiCodeBoxHeaders() + this.getWikiCodePB();
        
    }
    public String getWikiCodeNew() {
        //The idea is to build a large string that describes the Protein Box in Wiki Code.
        
        String[] vals = null;
        
        String wikiCode = "";
        
        wikiCode = this.getWikiCodePageHeaders() + lineSep; //extra line space.
        wikiCode = wikiCode + this.getWikiCodeBoxHeaders();
        wikiCode = wikiCode + this.getWikiCodePB() + lineSep;
        
        //Now for the text data.
        wikiCode = wikiCode + this.getWikiCodeSumHeaders();
        
        wikiCode = wikiCode + this.getWikiCodeSum() + lineSep;
        
        wikiCode = wikiCode + this.getWikiCodeSumFooters() + lineSep; //Extra Line Space
        
        //don't want the reference footers if there is no summary to reference.'
        //Update: Looks like we want the references all the time now..
        
        //if (data.getValue("Text",false).trim().compareTo("") != 0){
            wikiCode = wikiCode + this.getRefFooters();
        //}
        String cites = this.getFurtherReadingCitations();
        if (cites.compareTo("") != 0){
            wikiCode = wikiCode + this.getFurtherReadingHeaders();
            wikiCode += cites + lineSep;
            wikiCode += this.getFurtherReadingFooters();
            
        }
        
        wikiCode = wikiCode + lineSep + getWikiCodePageFooters() + lineSep;
        return wikiCode;
    }
    
    public String getWikiCodePageFooters(){
        return "{{protein-stub}}";
    }
    
    public void setCitationData(String[] citationData) {
        if (citationData == null){
            System.out.println("WARNING! Updated Gene with 0 Citations.");
            return;
        }
        if (citationData.length < 1) {
            System.out.println("WARNING! Updated Gene with 0 Citations.");
            return;
        } else {   
            System.out.println("Updated Gene with " + citationData.length + " Citations.");
        } 
        this.citationData = citationData;
    }
    
    public String[] getCitationData() {
        return citationData;
    }
    
    
}
